#!/usr/bin/env python
from utils import Logged, config, GClient, GAnswer, GStore
from mime import convert_to_b64
from gevent import sleep
from types import ListType

class GTest(Logged):
	def __init__(self, name, code = None, obj = None):
		self.obj = obj
		self.name = name
		if code[-1] == '\n':
			self.code = code[:-1]
		else:
			self.code = code

	def run(self):
		self.log('start test')
		found_none = False
		answers = []
		expects = []
		steps = []
		stop = False
		size = 0
		lines = self.code.split('\n')
		obj = config.get_obj(self.obj, copy = self.clone_obj)
		if obj is None:
			return GAnswer(False, load = 'No obj: %s' % self.obj)

		for l in lines:
			if l[0] == '#':
				continue
			if l[0] == 'sleep':
				sleep(float(l[1]))
			size += 1
			l = l.split()
			exp = None
			if len(l) == 2:
				exp = l[1]
			else:
				exp = 'ok'
			expects.append(exp)
			steps.append(l[0])

			self.log('step: %s' % l[0])
			if stop:
				answers.append('None')
				continue

			step = config.get_obj(l[0])
			if step is None:
				s = 'Step %s not found' % l[0]
				self.log_error(s)
				return GAnswer(False, load = s)

			try:
				func = getattr(obj, step.cmd)
			except Exception, e:
				self.log_error(e)
				return None

			if 'args' in step:
				try:
					ans = func(**step.args)
				except TypeError, e:
					return GAnswer(False, str(e))
			else:
				ans = func()

			ans.name = self.name + ': ' + l[0]
			self.loga(ans)
			found = False
			if isinstance(ans, GAnswer):
				for r in step.resp:
					ok_cnt = 0
					all_cnt = 0

					if 'ok' in r:
						all_cnt += 1
						if ans.ok == r['ok']:
							ok_cnt += 1

					if 'rc' in r:
						all_cnt += 1
						if ans.rc == r['rc']:
							ok_cnt += 1

					if 'str' in r:
						all_cnt += 1
						if ans.str == r['str']:
							ok_cnt += 1

					if 'str_reg' in r:
						all_cnt += 1
						import re
						if re.match(r['str_reg'], ans.str):
							ok_cnt += 1

					if 'load' in r:
						all_cnt += 1
						if ans.load == r['load']:
							ok_cnt += 1

					if 'struct' in r:
						all_cnt += 1
						if ans.struct == r['struct']:
							ok_cnt += 1

					if 'status' in r:
						all_cnt += 1
						if ans.status == r['status']:
							ok_cnt += 1

					if ok_cnt == all_cnt and all_cnt != 0:
						self.log('%s returns %s' % (l[0], r['id']))
						answers.append(r['id'])
						found = True
			else:
				for r in step['resp']:
					if 'rc' in r and r['rc'] == ans:
						answers.append(r['id'])
						found = True
						break

			if not found:
				self.log_warn('no matched response found for %s (use None)' % l[0])
				answers.append('None')
				found_none = True

		a = GAnswer()
		self.log('returned: %s' % repr(answers))
		self.log('expected: %s' % repr(expects))
		a.load = '\n'
		for i in range(size):
			if answers[i] == expects[i]:
				a.load += '%s:\t(%s == %s)\n' % (steps[i], answers[i], expects[i])
			else:
				a.load += '%s:\t(%s != %s)\n' % (steps[i], answers[i], expects[i])
		else:
			a.load = a.load[:-1]

		if answers == expects:
			self.log_crit('PASS')
			return a

		if found_none:
			for i in range(size):
				if answers[i] != expects[i] and answers[i] != 'None':
					break
			else:
				self.log_crit('PASS with Warnings')
				return a
		a.ok = False
		self.log_crit('FAIL')
		return a
	start = run

class TextTemplate(Logged):
	def __init__(self, template, txt_args = [], msg_args = []):
		from jinja2 import Template
		self.template = Template(template)
		self.txt_args = txt_args
		self.msg_args = msg_args
	
	def render(self, a):
		b = {}
		for i in a:
			if i in self.msg_args:
				m = config.get_msg(a[i])
				if m is None:
					return None
				convert_to_b64(m)
				m_str = m.as_string()
				b[i] = m_str
				b[i + '_len'] = str(len(m_str))
			elif i in self.txt_args:
				b[i] = a[i]
			elif i != 'template':
				self.log_error('unknown template param "%s"' % i)
		return self.template.render(b)

class TelnetClient(GClient):
	def send_templated_text(self,**a):
		t = config.get_obj(a['template'])
		r = t.render(a)
		return self.send_chunking(r)

